import {
  createStore,
  PluginFunctions,
  RenderViewer,
  Slot,
  SpecialZoomLevel,
  ViewerState,
} from "../../core";

import CurrentScale, { CurrentScaleProps } from "./CurrentScale";
import ShortcutHandler from "./ShortcutHandler";
import StoreProps from "./StoreProps";
import { ZoomMenuItemProps, ZoomPlugin } from "./interface";
import Zoom, { ZoomProps } from "./Zoom";
import ZoomIn, { ZoomInProps } from "./ZoomIn";
import ZoomOut, { ZoomOutProps } from "./ZoomOut";
import ZoomInButton from "./ZoomInButton";
import ZoomInMenuItem from "./ZoomInMenuItem";
import ZoomOutButton from "./ZoomOutButton";
import ZoomOutMenuItem from "./ZoomOutMenuItem";
import ZoomPopover from "./ZoomPopover";
import { useMemo } from "react";

export interface ZoomPluginProps {
  enableShortcuts?: boolean;
}

const zoomPlugin = (props?: ZoomPluginProps): ZoomPlugin => {
  const zoomPluginProps = useMemo(
    () => Object.assign({}, { enableShortcuts: true }, props),
    []
  );
  const store = useMemo(() => createStore<StoreProps>({}), []);

  const CurrentScaleDecorator = (props: CurrentScaleProps) => (
    <CurrentScale {...props} store={store} />
  );

  const ZoomInDecorator = (props: ZoomInProps) => (
    <ZoomIn {...props} store={store} />
  );

  const ZoomInButtonDecorator = () => (
    <ZoomInDecorator>{(props) => <ZoomInButton {...props} />}</ZoomInDecorator>
  );

  const ZoomInMenuItemDecorator = (props: ZoomMenuItemProps) => (
    <ZoomInDecorator>
      {(p) => (
        <ZoomInMenuItem
          onClick={() => {
            p.onClick();
            props.onClick();
          }}
        />
      )}
    </ZoomInDecorator>
  );

  const ZoomOutDecorator = (props: ZoomOutProps) => (
    <ZoomOut {...props} store={store} />
  );

  const ZoomOutButtonDecorator = () => (
    <ZoomOutDecorator>
      {(props) => <ZoomOutButton {...props} />}
    </ZoomOutDecorator>
  );

  const ZoomOutMenuItemDecorator = (props: ZoomMenuItemProps) => (
    <ZoomOutDecorator>
      {(p) => (
        <ZoomOutMenuItem
          onClick={() => {
            p.onClick();
            props.onClick();
          }}
        />
      )}
    </ZoomOutDecorator>
  );

  const ZoomDecorator = (props: ZoomProps) => <Zoom {...props} store={store} />;

  const ZoomPopoverDecorator = () => (
    <ZoomDecorator>{(props) => <ZoomPopover {...props} />}</ZoomDecorator>
  );

  const renderViewer = (props: RenderViewer): Slot => {
    const { slot } = props;
    if (!zoomPluginProps.enableShortcuts) {
      return slot;
    }

    const updateSlot: Slot = {
      children: (
        <>
          <ShortcutHandler containerRef={props.containerRef} store={store} />
          {slot.children}
        </>
      ),
    };
    return { ...slot, ...updateSlot };
  };

  return {
    renderViewer,
    install: (pluginFunctions: PluginFunctions) => {
      store.update("zoom", pluginFunctions.zoom);
    },
    onViewerStateChange: (viewerState: ViewerState) => {
      store.update("scale", viewerState.scale);
      return viewerState;
    },
    zoomTo: (scale: number | SpecialZoomLevel) => {
      const zoom = store.get("zoom");
      if (zoom) {
        zoom(scale);
      }
    },
    CurrentScale: CurrentScaleDecorator,
    ZoomIn: ZoomInDecorator,
    ZoomInButton: ZoomInButtonDecorator,
    ZoomInMenuItem: ZoomInMenuItemDecorator,
    ZoomOut: ZoomOutDecorator,
    ZoomOutButton: ZoomOutButtonDecorator,
    ZoomOutMenuItem: ZoomOutMenuItemDecorator,
    Zoom: ZoomDecorator,
    ZoomPopover: ZoomPopoverDecorator,
  };
};

export default zoomPlugin;
